package com.yingxin.yx.framework.security.handler;

import com.alibaba.fastjson.JSON;
import com.yingxin.yx.framework.security.userdetails.AccountUserDetailsService;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationListener;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Date;

@Component
public class BadCredentialsListener implements ApplicationListener<AuthenticationFailureBadCredentialsEvent> {

    @SuppressWarnings("rawtypes")
    @Autowired
    @Qualifier(value = "stringRedisTemplate")
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private AccountUserDetailsService accountUserDetailsService;

    @Override
    public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent authenticationFailureBadCredentialsEvent) {
        String username = authenticationFailureBadCredentialsEvent.getAuthentication().getPrincipal().toString();
        String region = "login_failure";
        Object obj = stringRedisTemplate.opsForHash().get(region, username);
        if (obj == null) {
            // 第一次失败
            BadCredentialsCount badCredentialsCount = new BadCredentialsCount(1, new Date());
            stringRedisTemplate.opsForHash().put(region, username, JSON.toJSONString(badCredentialsCount));
        } else {
            BadCredentialsCount badCredentialsCount = JSON.parseObject(obj.toString(), BadCredentialsCount.class);
            long timeDiff = new Date().getTime() - badCredentialsCount.getFirstTime().getTime();
            if (timeDiff < 24 * 60 * 60 * 1000) {
                // 24小时内 可以失败x次
                // badCredentialsCount.setCount(badCredentialsCount.getCount() + 1);
                stringRedisTemplate.opsForHash().put(region, username, JSON.toJSONString(badCredentialsCount));
                /*if (badCredentialsCount.getCount() < 6) {
                    stringRedisTemplate.opsForHash().put(region, username, JSON.toJSONString(badCredentialsCount));
                } else {
                    // 锁定
                    accountUserDetailsService.lockUser(username);
                }*/
            } else {
                // 24小时之后，重新计数
                badCredentialsCount = new BadCredentialsCount(1, new Date());
                stringRedisTemplate.opsForHash().put(region, username, JSON.toJSONString(badCredentialsCount));
            }
        }
    }

    @Data
    static class BadCredentialsCount implements Serializable {

        private static final long serialVersionUID = 2883746088787775724L;

        private Integer count;

        private Date firstTime;

        public BadCredentialsCount() {

        }

        public BadCredentialsCount(Integer count, Date firstTime) {
            this.count = count;
            this.firstTime = firstTime;
        }

    }

}

